﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Collections.Generic;
using System.Data;
using static Utility.WinAPI;

namespace Utility
{
    /// <summary>
    /// 通用类组件
    /// <para>封装了一些自己写的常用的函数</para>
    /// </summary>
    public static class Common
    {
        public static Rectangle GetFullscreen()
        {
            int X = GetSystemMetrics(SystemMetricsFlags.SM_CXSCREEN);
            int Y = GetSystemMetrics(SystemMetricsFlags.SM_CYSCREEN);
            if (X % 10 == 0 && Y % 10 == 0)
            {
                return new Rectangle(0, 0, X, Y);
            }
            else
            {
                TransformToPixels(X, Y, out int x, out int y);
                return new Rectangle(0, 0, x, y);
            }
        }

        #region Methods
        /// <summary>
        /// 数据库的数据转<see cref="List<T>"/>
        /// </summary>
        /// <typeparam name="T">模型</typeparam>
        /// <param name="DataRowCollection">行的集合</param>
        /// <returns>模型集合</returns>
        public static IList<T> DataRowCollectionToList<T>(DataRowCollection DataRowCollection) where T : new()
        {
            IList<T> List = new List<T>();
            foreach (DataRow Row in DataRowCollection)
            {
                T Instance = Activator.CreateInstance<T>();
                foreach (var Property in typeof(T).GetProperties())
                {
                    Property.SetValue(Instance, Row[Property.Name]);
                }
                List.Add(Instance);
            }
            return List;
        }

        /// <summary>
        /// 检测是否有流氓杀毒软件影响本应用程序正常功能
        /// <para>有的话会弹个窗</para>
        /// </summary>
        /// <param name="ShowWarn">是否显示警告</param>
        /// <returns>
        /// <see cref="DialogResult.Cancel"/>代表未显示对话框,或对话框正常关闭
        /// <see cref="DialogResult.Yes"/>代表"不再提示"被点击
        /// </returns>
        public static DialogResult WarnCheck(bool ShowWarn = true)
        {
            if (!ShowWarn || Process.GetProcessesByName("360Safe").Length + Process.GetProcessesByName("360Tray").Length == 0)
            {
                return DialogResult.Cancel;
            }

            string Fullpath = Process.GetCurrentProcess().MainModule.FileName;
            string Exename = Path.GetFileNameWithoutExtension(Fullpath);

            var Warn = new Form()
            {
                AutoScaleDimensions = new SizeF(8F, 15F),
                AutoScaleMode = AutoScaleMode.Font,
                ClientSize = new Size(800, 400),
                FormBorderStyle = FormBorderStyle.FixedDialog,
                MaximizeBox = false,
                MinimizeBox = false,
                Text = "兼容性警告",
                ShowIcon = false,
                ShowInTaskbar = false
            };

            CheckBox CheckBox = new CheckBox()
            {
                AutoSize = true,
                Checked = false,
                Text = "不再显示",
                Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134),
                Location = new Point(50, 350)
            };

            CheckBox.CheckedChanged += ((s, e) => Warn.DialogResult = DialogResult.Yes);

            Warn.Controls.Add(new Label()
            {
                AutoSize = true,
                Font = new Font("宋体", 17F, FontStyle.Regular, GraphicsUnit.Point, 134),
                Location = new Point(50, 50),
                Text = $"{Exename} 兼容性警告!"
            });

            Warn.Controls.Add(new Label()
            {
                AutoSize = true,
                Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134),
                Location = new Point(50, 120),
                Text = $"您正在运行“360安全卫士”\n其可能导致 {Exename} 在某些情况下失效甚至崩溃。"
            });

            Warn.Controls.Add(new Label()
            {
                AutoSize = true,
                Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134),
                Location = new Point(50, 200),
                Text = $"要避免此问题，请确保将 {Exename} \n添加到360的“信任列表”中，并重启360。\n（若上一版本已添加过，请删除记录后重新添加）"
            });

            Warn.Controls.Add(new Label()
            {
                AutoSize = true,
                Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134),
                Location = new Point(50, 300),
                Text = $"{Exename} 位于:"
            });

            Warn.Controls.Add(new TextBox()
            {
                BackColor = SystemColors.Window,
                Location = new Point(300, 300),
                ReadOnly = true,
                Size = new Size(450, 25),
                Text = Fullpath
            });

            Warn.Controls.Add(CheckBox);

            return Warn.ShowDialog();

        }

        /// <summary>
        /// 程序初始化时调用,检测是否已有实例运行
        /// <para>使用进程名和ID进行检测,而非互斥锁<see cref="System.Threading.Mutex"/></para>
        /// </summary>
        /// <exception cref="StartException"></exception>
        /// <param name="ProcessName">要检测是否已经启动的进程名,默认为当前程序名<see cref="Process.GetCurrentProcess().ProcessName"/> </param>
        public static void IsStart(string ProcessName = "")
        {
            if (Process.GetProcessesByName(string.IsNullOrEmpty(ProcessName) || ProcessName == Process.GetCurrentProcess().ProcessName ? Process.GetCurrentProcess().ProcessName : ProcessName).Length > Convert.ToInt32(string.IsNullOrEmpty(ProcessName) || ProcessName == Process.GetCurrentProcess().ProcessName))
            {
                throw new StartException($"检测到已有同名实例运行,进程名:{ProcessName}", "IsStart");
            }
        }

        /// <summary>
        /// 程序初始化时调用,检测程序是否完整
        /// </summary>
        /// <exception cref="StartException"></exception>
        /// <param name="Directory">目录,默认为当前目录<see cref="AppDomain.CurrentDomain.BaseDirectory"/></param>
        /// <param name="Filename">在目录<see cref="Directory"/>下所有要检测的文件名</param>
        public static void CheckFile(string[] Filename, string Directory = "")
        {
            foreach (string str in Filename)
            {
                if (!File.Exists((string.IsNullOrEmpty(Directory) ? AppDomain.CurrentDomain.BaseDirectory : Directory) + str))
                {
                    throw new StartException($"检测到本软件文件不完整,缺失文件:{str}", "CheckFile");
                }
            }
        }

        /// <summary>
        /// 由像素转为那个乱七八糟的单位,
        /// 比例一般是1.25
        /// </summary>
        /// <param name="pxX">以像素为单位的X</param>
        /// <param name="pxY">以像素为单位的Y</param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        public static void TransformFromPixels(int pxX, int pxY, out int X, out int Y)
        {
            System.Windows.Media.Matrix matrix = new HwndSource(new HwndSourceParameters()).CompositionTarget.TransformToDevice;
            X = (int)(pxX / matrix.M11);
            Y = (int)(pxY / matrix.M22);
        }

        /// <summary>
        /// 由像素转为那个乱七八糟的单位,
        /// 比例一般是1.25
        /// </summary>
        /// <param name="pxX">以像素为单位的X</param>
        /// <param name="pxY">以像素为单位的Y</param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        public static Point TransformFromPixels(int pxX, int pxY)
        {
            System.Windows.Media.Matrix matrix = new HwndSource(new HwndSourceParameters()).CompositionTarget.TransformToDevice;
            return new Point((int)(pxX / matrix.M11), (int)(pxY / matrix.M22));
        }

        /// <summary>
        /// 由那个乱七八糟的单位转为像素,
        /// 比例一般是1.25
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// /// <param name="pxX">以像素为单位的X</param>
        /// <param name="pxY">以像素为单位的Y</param>
        public static void TransformToPixels(int X, int Y, out int pxX, out int pxY)
        {
            System.Windows.Media.Matrix Matrix = new HwndSource(new HwndSourceParameters()).CompositionTarget.TransformToDevice;
            pxX = (int)(X * Matrix.M11);
            pxY = (int)(Y * Matrix.M22);
        }

        /// <summary>
        /// 由那个乱七八糟的单位转为像素,
        /// 比例一般是1.25
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// /// <param name="pxX">以像素为单位的X</param>
        /// <param name="pxY">以像素为单位的Y</param>
        public static Point TransformToPixels(int X, int Y)
        {
            System.Windows.Media.Matrix Matrix = new HwndSource(new HwndSourceParameters()).CompositionTarget.TransformToDevice;
            return new Point((int)(X * Matrix.M11), (int)(Y * Matrix.M22));
        }

        public static bool IsPowerOnline() => SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online;
        #endregion
    }
}
